package com.harmontronics.hanma.paas.paas.domain.iam.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.harmontronics.hanma.paas.paas.consts.NumberEnum;
import com.harmontronics.hanma.paas.paas.domain.organization.entity.UserGroupTree;
import com.harmontronics.hanma.paas.paas.domain.organization.entity.valueobject.Constants;
import com.harmontronics.hanma.paas.paas.domain.iam.entity.valueobject.HmUserGroupFileds;
import com.harmontronics.hanma.paas.paas.domain.iam.entity.valueobject.HmUserGroupManageFields;
import com.harmontronics.hanma.paas.paas.domain.organization.entity.valueobject.I18nKeyEnum;
import com.harmontronics.hanma.paas.paas.domain.iam.repository.persistence.HmUserGroupManageRepository;
import com.harmontronics.hanma.paas.paas.domain.iam.repository.persistence.HmUserGroupRepository;
import com.harmontronics.hanma.paas.paas.domain.iam.entity.HmUserGroup;
import com.harmontronics.hanma.paas.paas.domain.iam.repository.po.HmUserGroupManagePO;
import com.harmontronics.hanma.paas.paas.domain.organization.service.HmOrgService;
import com.harmontronics.hanma.paas.paas.domain.organization.service.IHmOrgService;
import com.harmontronics.hanma.paas.paas.exception.ErrorKeyException;
import java.util.ArrayList;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.harmontronics.hanma.paas.paas.common.PageBase;

import com.harmontronics.hanma.paas.paas.domain.iam.repository.mapper.HmUserGroupMapper;
import com.harmontronics.hanma.paas.paas.domain.iam.repository.po.HmUserGroupPO;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;

@Service("hmUserGroupService")
@DS("#header.App-Unique")
public class HmUserGroupService{

    @Autowired
    private HmUserGroupRepository hmUserGroupRepository;

    @Autowired
    private HmUserGroupMapper hmUserGroupMapper;

    @Autowired
    private HmUserGroupManageRepository hmUserGroupManageRepository;

    @Autowired
    private IHmOrgService hmOrgService;

    @Autowired
    private HmUserGroupManageService hmUserGroupManageService;


    public void save(HmUserGroup hmUserGroup){
        HmUserGroupPO po =  BeanUtil.toBean(hmUserGroup,HmUserGroupPO.class);

        checkUserGroupNameValid(po);
        // 排序，父节点组合
        assignNewValueToUserGroup(po);
        po.setDeleted(Integer.valueOf(0));
        hmUserGroupMapper.insert(po);
    }

    private void checkUserGroupNameValid(HmUserGroupPO userGroup) {
        List<HmUserGroupPO> userGroupList =
                hmUserGroupMapper.selectList(
                        new QueryWrapper<HmUserGroupPO>()
                                .eq(HmUserGroupFileds.NAME, userGroup.getName())
                                .eq(HmUserGroupFileds.PARENT_ID, userGroup.getParentId()));
        if (CollectionUtils.isNotEmpty(userGroupList)) {
            throw new ErrorKeyException(I18nKeyEnum.CURRENT_GROUP_NAME_EXIST);
        }
    }

    private void assignNewValueToUserGroup(HmUserGroupPO userGroup) {
        HmUserGroupPO currentGroup = hmUserGroupMapper.selectById(userGroup.getId());
        if (currentGroup == null || (userGroup.getParentId() != null && !currentGroup.getParentId()
                .equals(userGroup.getParentId()))) {
            Integer serialNum = hmUserGroupMapper
                    .selectMaxSerialNum(userGroup.getParentId());
            if (serialNum == null) {
                serialNum = NumberEnum.ZERO.getNum();
            }
            userGroup.setSerialNum(serialNum + NumberEnum.ONE.getNum());
            if(userGroup.getParentId()!=null) {
                HmUserGroupPO parentUserGroup = hmUserGroupMapper.selectById(userGroup.getParentId());
                String parentIds = parentUserGroup.getParentIds();
                parentIds = parentIds == null ? "" : parentIds;
                userGroup.setParentIds(
                        parentIds
                                + Constants.LEFT_SQUARE_BRACKETS
                                + parentUserGroup.getId()
                                + Constants.RIGHT_SQUARE_BRACKETS);
            }
        }
    }

    public void update(HmUserGroup hmUserGroup){
        HmUserGroupPO hmUserGroupPO =BeanUtil.toBean(hmUserGroup,HmUserGroupPO.class);

        // 根据id查询出修改前的数据
        checkUserGroupNameValid(hmUserGroupPO);
        // 排序，父节点组合
        assignNewValueToUserGroup(hmUserGroupPO);
        hmUserGroupMapper.updateById(hmUserGroupPO);
    }


    public void remove(List<Long> ids){
        ids.forEach(groupId->{
            checkGroupHasChild(groupId);
            // 如果用户组里面有管理员或者成员无法删除提示“该用户组还有成员或者管理员无法删除,请先移除”
            checkUSerGroupManageAndMember(groupId);
            //当前节点后的所有节点要重新排序
            HmUserGroupPO currentUserOrg = hmUserGroupMapper
                    .selectOne(new QueryWrapper<HmUserGroupPO>().eq(HmUserGroupFileds.ID, groupId));
            List<HmUserGroupPO> userGroupList =
                    hmUserGroupMapper.selectList(
                            new QueryWrapper<HmUserGroupPO>()
                                    .eq(HmUserGroupFileds.PARENT_ID,
                                            currentUserOrg.getParentId())
                                    .ge(HmUserGroupFileds.SERIAL_NUM,
                                            currentUserOrg.getSerialNum()));
            userGroupList.forEach(
                    e -> {
                        Integer serialNum = e.getSerialNum();
                        e.setSerialNum(serialNum - NumberEnum.ONE.getNum());
                    });
            hmUserGroupRepository.updateBatchById(userGroupList);
            hmUserGroupMapper.deleteById(groupId);
        });
    }

    /**
     * 判断是否存在子节点
     */
    private void checkGroupHasChild(Long groupId) {
        List<HmUserGroupPO> userGroupList =
                hmUserGroupMapper.selectList(
                        new QueryWrapper<HmUserGroupPO>()
                                .eq(HmUserGroupFileds.PARENT_ID, groupId));
        if (CollectionUtils.isNotEmpty(userGroupList)) {
            throw new ErrorKeyException(I18nKeyEnum.CURRENT_GROUP_HAVE_MEMBER);
        }
    }

    /**
     * 如果用户组里面有管理员或者成员无法删除提示“该用户组还有成员或者管理员无法删除,请先移除”
     */
    private void checkUSerGroupManageAndMember(Long groupId) {
        List<HmUserGroupManagePO> userGroupManages =
                hmUserGroupManageRepository.list(
                        new QueryWrapper<HmUserGroupManagePO>()
                                .eq(HmUserGroupManageFields.USER_GROUP_ID, groupId));
        List<HmUserGroupManagePO> memberList =
                hmUserGroupManageRepository.list(
                        new QueryWrapper<HmUserGroupManagePO>()
                                .eq(HmUserGroupManageFields.USER_GROUP_ID, groupId));
        if (CollectionUtils.isNotEmpty(userGroupManages) || CollectionUtils
                .isNotEmpty(memberList)) {
            throw new ErrorKeyException(I18nKeyEnum.CURRENT_GROUP_HAVE_MEMBER);
        }
    }

    public List<HmUserGroup> getList(){
        List<HmUserGroupPO> pos =  hmUserGroupRepository.list();
        return Convert.toList(HmUserGroup.class,pos) ;
    }

    public PageBase<HmUserGroup> getList(int pageNo,int pageSize){
        Page<HmUserGroupPO> page = new Page<>(pageNo, pageSize);
        IPage<HmUserGroupPO> resultPage =
                    hmUserGroupRepository.selectPage(Wrappers.emptyWrapper(),page);
        return PageBase.from(resultPage,HmUserGroup.class);
    }

    public List<UserGroupTree> selectUserGroupTree() {
        List<UserGroupTree> userGroupTree = hmUserGroupMapper.selectUserGroupTree();
        userGroupTree.forEach(e -> e.setIsRoot(Boolean.TRUE));
        return userGroupTree;
    }

    /**
     * 获取在当前应用下，用户的用户组树
     */
    public List<UserGroupTree> selectUserGroupTreeByAppUserId( Long userId) {
        List<UserGroupTree> userGroupTree = hmUserGroupMapper
                .selectUserGroupTreeWithAppUserId(userId);
        userGroupTree.forEach(e -> e.setIsRoot(Boolean.TRUE));
        return userGroupTree;
    }

    /**
     * 上移用户组节点
     */
    @Transactional(rollbackFor = Exception.class)
    public void moveUp(Long id) {
        move( id, Constants.UP);
    }

    /**
     * 下移用户组节点
     */
    @Transactional(rollbackFor = Exception.class)
    public void moveDown(Long id) {
        move(id,Constants.DOWN);
    }

    private void move(Long id, String move) {
        // 获取当前节点并判空
        HmUserGroupPO currentUserGroup = currentUserGroupWithId(id);
        //checkUserCanMove(userId, id);
        Integer moveNum =
                Constants.UP.equalsIgnoreCase(move)
                        ? currentUserGroup.getSerialNum() - NumberEnum.ONE.getNum()
                        : currentUserGroup.getSerialNum() + NumberEnum.ONE.getNum();
        currentUserGroup.setSerialNum(moveNum);

        // 查询当前节点下的所有子节点
        List<HmUserGroupPO> userGroupList = userGroupNodeWithParentId(currentUserGroup);

        // 移动节点
        Map<Integer, HmUserGroupPO> userGroupMap =
                userGroupList.stream()
                        .collect(Collectors.toMap(HmUserGroupPO::getSerialNum, Function.identity()));
        HmUserGroupPO downUserGroup = userGroupMap.get(moveNum);
        if (Constants.UP.equals(move)) {
            downUserGroup.setSerialNum(moveNum + NumberEnum.ONE.getNum());
        } else {
            downUserGroup.setSerialNum(moveNum - NumberEnum.ONE.getNum());
        }

        List<HmUserGroupPO> updateUserGroups = new ArrayList<>();
        updateUserGroups.add(currentUserGroup);
        updateUserGroups.add(downUserGroup);
        hmUserGroupRepository.updateBatchById(updateUserGroups);
    }

    private HmUserGroupPO currentUserGroupWithId(Long id) {
        HmUserGroupPO userGroup =
                hmUserGroupMapper.selectOne(
                        new QueryWrapper<HmUserGroupPO>().eq(HmUserGroupFileds.ID, id));
        if (userGroup == null) {
            throw new ErrorKeyException(I18nKeyEnum.CURRENT_NODE_NOT_EXIST);
        }
        return userGroup;
    }

    /**
     * 获取当前用户 判断当前修改的节点是否在 当前用户所在的用户组管理范围内
     */
    private void checkUserCanMove(Long userId, Long id) {
        if (userId == null) {
            throw new ErrorKeyException(I18nKeyEnum.USER_NOT_EXIST);
        }

        /**
        User user = userService.getById(userId);
        boolean isAdmin = user.getIsSuperAdmin() == null ? false : user.getIsSuperAdmin();
        if (isAdmin){
            return;
        }*/


        // 1.根据id 获取当前用户所在的组织架构及其父节点
        List<Long> userOrgIds = hmOrgService.selectOrgParentIdWithUserId(userId);
        // 2.从用户组 管理员及成员中获取所在的用户组
        List<Long> userGroupIds =
                hmUserGroupManageService.selectGroupIdsWithOrgIdAndUserId(userOrgIds, userId);
        if (CollectionUtils.isEmpty(userGroupIds) || !userGroupIds.contains(id)) {
            throw new ErrorKeyException(I18nKeyEnum.CURRENT_GROUP_HAVE_MEMBER);
        }

    }

    private List<HmUserGroupPO> userGroupNodeWithParentId(HmUserGroupPO currentUserGroup) {
        List<HmUserGroupPO> userGroupList =
                hmUserGroupMapper.selectList(
                        new QueryWrapper<HmUserGroupPO>()
                                .eq(HmUserGroupFileds.PARENT_ID,
                                        currentUserGroup.getParentId())
                                .orderByAsc(HmUserGroupFileds.SERIAL_NUM));
        if (CollectionUtils.isEmpty(userGroupList)) {
            throw new ErrorKeyException(I18nKeyEnum.CURRENT_NODE_NOT_EXIST);
        }
        return userGroupList;
    }

    public void validateField(Long appId, long id, String key, String value, long parentId) {
        QueryWrapper<HmUserGroupPO> wrapper = new QueryWrapper<>();
        wrapper.eq(HmUserGroupFileds.APP_ID, appId);
        wrapper.eq(key, value);
        wrapper.eq(HmUserGroupFileds.PARENT_ID, parentId);

        // 修改
        if (NumberEnum.ZERO.getNumLong() != id) {
            wrapper.ne(HmUserGroupFileds.ID, id);
        }

        validateFieldImpl(wrapper);
    }

    private void validateFieldImpl(QueryWrapper<HmUserGroupPO> wrapper) {
        HmUserGroupPO userGroup = hmUserGroupMapper.selectOne(wrapper);

        if (Optional.ofNullable(userGroup).isPresent()) {
            throw new ErrorKeyException(I18nKeyEnum.CURRENT_GROUP_NAME_EXIST);
        }
    }

    /**
     * 根据父节点查询出所有的子节点
     */
    public List<Long> selectChildIdWithParentId(Long userGroupId) {
        HmUserGroupPO userGroup = hmUserGroupMapper.selectById(userGroupId);
        String parentIds = "";
        if(!Optional.ofNullable(userGroup).isPresent()){
            return new ArrayList<Long>();
        }
        if (StringUtils.isNotBlank(userGroup.getParentIds())) {
            parentIds = userGroup.getParentIds();
        }
        List<HmUserGroupPO> userGroupList = hmUserGroupMapper.selectList(new QueryWrapper<HmUserGroupPO>()
                .likeRight(HmUserGroupFileds.PARENT_IDS,
                        parentIds + Constants.LEFT_SQUARE_BRACKETS + userGroupId
                                + Constants.RIGHT_SQUARE_BRACKETS));
        return userGroupList.stream().mapToLong(HmUserGroupPO::getId).boxed().collect(Collectors.toList());
    }

    public HmUserGroupPO selectParentGroupWithChildrenId(Long groupId) {
        return hmUserGroupMapper.selectParentGroupWithChildrenId(groupId);
    }

}